package controllers

import (
    "encoding/json"
    "github.com/beego/beego/v2/server/web"
    "volux/models"
    "volux/utils"
    "time"
    "strings"
    "fmt"
)

// GatewayController 管理网关节点
type GatewayController struct {
    web.Controller
}

// 获取etcd客户端的辅助函数
func getEtcdClient() (*utils.EtcdClient, error) {
    endpoints, err := web.AppConfig.String("etcd::endpoints")
    if err != nil {
        return nil, err
    }
    username, err := web.AppConfig.String("etcd::username")
    if err != nil {
        return nil, err
    }
    password, err := web.AppConfig.String("etcd::password")
    if err != nil {
        return nil, err
    }
    
    return utils.NewEtcdClient(
        strings.Split(endpoints, ","),
        username,
        password,
    )
}

// SPDKStatus 表示SPDK服务状态
type SPDKStatus struct {
    Status      string            `json:"status"`
    Version     string            `json:"version"`
    Uptime      string           `json:"uptime"`
    StartTime   string           `json:"start_time"`
    Services    []string         `json:"services"`
    Performance map[string]int64 `json:"performance"`
}

// Health 返回网关和SPDK健康状态
func (c *GatewayController) Health() {
    response := map[string]interface{}{
        "code": 200,
        "msg": "success",
        "data": map[string]interface{}{
            "status": "healthy",
            "services": map[string]interface{}{
                "etcd": checkEtcdHealth(),
                "spdk": checkSPDKHealth(),
            },
            "timestamp": time.Now().Format(time.RFC3339),
        },
    }

    // 设置响应数据到context中供中间件使用
    c.Ctx.Input.SetData("json", response)
    
    // 设置响应头
    c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8")
    
    // 发送响应
    c.Data["json"] = response
    c.ServeJSON()
}

// 检查etcd健康状态
func checkEtcdHealth() map[string]interface{} {
    utils.LogMethodEnter()
    var err error
    defer func() {
        utils.LogMethodExit(err)
    }()

    client := utils.GetEtcdClient()
    if client == nil {
        err = fmt.Errorf("etcd client not available")
        return map[string]interface{}{
            "status": "unhealthy",
            "error": err.Error(),
        }
    }

    if !utils.CheckEtcdConnection(client) {
        err = fmt.Errorf("failed to connect to etcd")
        return map[string]interface{}{
            "status": "unhealthy",
            "error": err.Error(),
        }
    }

    return map[string]interface{}{
        "status": "healthy",
    }
}

// 检查SPDK健康状态
func checkSPDKHealth() map[string]interface{} {
    utils.LogMethodEnter()
    var err error
    defer func() {
        utils.LogMethodExit(err)
    }()

    client := utils.GetSPDKClient()
    if client == nil {
        err = fmt.Errorf("spdk client not available")
        return map[string]interface{}{
            "status": "unhealthy",
            "error": err.Error(),
        }
    }

    // 获取SPDK版本信息来验证连接
    version, err := client.GetVersion()
    if err != nil {
        return map[string]interface{}{
            "status": "unhealthy",
            "error": err.Error(),
        }
    }

    return map[string]interface{}{
        "status": "healthy",
        "version": version,
    }
}

// AddGateway 添加网关节点
func (c *GatewayController) AddGateway() {
    var gateway models.GatewayNode
    if err := json.Unmarshal(c.Ctx.Input.RequestBody, &gateway); err != nil {
        utils.ErrorResponse(c.Controller, 400, "Invalid request body")
        return
    }

    // 将节点信息存储到 etcd
    etcdClient, err := getEtcdClient()
    if err != nil {
        c.Ctx.WriteString("Failed to connect to etcd")
        return
    }

    gatewayJSON, _ := json.Marshal(gateway)
    if err := etcdClient.Put("/gateways/"+gateway.ID, string(gatewayJSON)); err != nil {
        c.Ctx.WriteString("Failed to store gateway in etcd")
        return
    }

    c.Ctx.WriteString("Gateway added successfully")
}

// Heartbeat 更新网关节点心跳
func (c *GatewayController) Heartbeat() {
    id := c.GetString("id")
    if id == "" {
        c.Ctx.WriteString("Invalid request")
        return
    }

    etcdClient, err := getEtcdClient()
    if (err != nil) {
        c.Ctx.WriteString("Failed to connect to etcd")
        return
    }

    // 更新节点的最后心跳时间
    gatewayJSON, err := etcdClient.Get("/gateways/" + id)
    if err != nil {
        c.Ctx.WriteString("Gateway not found")
        return
    }

    var gateway models.GatewayNode
    if err := json.Unmarshal([]byte(gatewayJSON), &gateway); err != nil {
        c.Ctx.WriteString("Failed to parse gateway data")
        return
    }

    gateway.LastHeartbeat = time.Now()
    updatedGatewayJSON, _ := json.Marshal(gateway)

    // 使用 TTL 更新节点信息（假设 TTL 为 600 秒）
    if err := etcdClient.PutWithTTL("/gateways/"+id, string(updatedGatewayJSON), 600); err != nil {
        c.Ctx.WriteString("Failed to update heartbeat")
        return
    }

    c.Ctx.WriteString("Heartbeat updated successfully")
}

// GetGatewayVersion writes the gateway and SPDK version information to the response context.
// It currently returns a hardcoded version string for both the gateway and SPDK.
func (c *GatewayController) GetGatewayVersion() {
    spdkClient := utils.GetSPDKClient()
    spdkVersion := "unknown"
    if spdkClient != nil {
        version, err := spdkClient.GetVersion()
        if err == nil {
            spdkVersion = version
        }
    }
    gwVersion, err := web.AppConfig.String("gateway::version")
    if err != nil {
        gwVersion = "unknown"
    }
    c.Ctx.WriteString(fmt.Sprintf("Gateway Version: %s, SPDK Version: %s", gwVersion, spdkVersion))
}

// GetGateways retrieves a list of gateways.
// This method is part of the GatewayController and is responsible for
// handling the logic to fetch and return gateway data.
func (c *GatewayController) GetGateways() {
    _, err := getEtcdClient()
    if err != nil {
        c.Ctx.WriteString("Failed to connect to etcd")
        return
    }

    c.Data["json"] = "sssss"
    c.ServeJSON()
}

// GetSubsystemStats 获取子系统统计信息
func (c *GatewayController) GetSubsystemStats() {
    client := utils.GetSPDKClient()
    if client == nil {
        c.Ctx.WriteString("SPDK client not available")
        return
    }

    stats, err := client.GetSubsystemStats()
    if err != nil {
        c.Ctx.WriteString(fmt.Sprintf("Failed to get subsystem stats: %v", err))
        return
    }

    c.Data["json"] = stats
    c.ServeJSON()
}
